/* global ENV_DEVELOPMENT */
import config from 'config'
import WebSocketClient from './WebSocketClient'

let api = null
export { api as default }

export function initApi({ store, token, clientId, inviteToken }) {
	if (api) {
		try { api.close() } catch (e) { /* ignore */ }
	}
	api = new WebSocketClient(`${config.api.socket}`, { token, clientId, inviteToken })
	console.info('[API] websocket URL', config.api.socket)
	api.connect()

	api.on('closed', () => {
		console.warn('socket closed')
	})

	api.on('error', (error) => {
		console.error('socket', error)
	})

	api.on('warning', (warning) => {
		console.warn('socket', warning)
	})

	api.on('message', (message) => {
		let [name, ...data] = message
		if (data.length === 1) data = data[0]
		const module = name.split('.')[0]
		if (store._actions[`${module}/api::${name}`]) {
			store.dispatch(`${module}/api::${name}`, data)
		} else if (store._actions[`api::${name}`]) {
			store.dispatch(`api::${name}`, data)
		}
	})

	api.on('log', ({direction, data}) => {
		const payload = JSON.parse(data)
		const action = payload.shift()
		let correlationId
		if (Number.isInteger(payload[0])) {
			correlationId = payload.shift()
		}
		if (['ping', 'pong'].includes(action)) return // mute pingpong
		if (ENV_DEVELOPMENT) {
			console.log(
				`%c${direction === 'send' ? '<<=' : '=>>'} %c${'socket'.padEnd(11)} %c${action.padEnd(32)} %c${String(correlationId || '').padEnd(6)}`,
				direction === 'send' ? 'color: blue' : 'color: green',
				'color: grey',
				'color: purple',
				'color: darkslategray',
				...payload
			)
		}
	})

	api.uploadFile = function(file, filename, url, width, height) {
		url = url || config.api.upload
		const data = new FormData()
		data.append('file', file, filename)
		if (width) data.append('width', width)
		if (height) data.append('height', height)
		const request = new XMLHttpRequest()
		request.open('POST', url)
		request.setRequestHeader('Accept', 'application/json')
		if (api._config.token) {
			request.setRequestHeader('Authorization', `Bearer ${api._config.token}`)
		} else if (api._config.clientId) {
			request.setRequestHeader('Authorization', `Client ${api._config.clientId}`)
		}
		request.send(data)
		return request
	}

	// TODO unify, rename, progress support
	api.uploadFilePromise = function(file, filename, url) {
		url = url || config.api.upload
		const data = new FormData()
		data.append('file', file, filename)
		const authHeader = api._config.token ? `Bearer ${api._config.token}`
			: (api._config.clientId ? `Client ${api._config.clientId}` : null)
		const headers = { Accept: 'application/json' }
		if (authHeader) headers.Authorization = authHeader
		return fetch(url, {
			method: 'POST',
			body: data,
			headers
		}).then(async response => {
			const ct = response.headers.get('content-type') || ''
			if (!response.ok) {
				const text = await response.text().catch(() => '')
				throw new Error(`Upload failed (${response.status}): ${text.slice(0, 200)}`)
			}
			if (ct.includes('application/json')) {
				return response.json()
			} else {
				const text = await response.text().catch(() => '')
				throw new Error(`Unexpected response content-type: ${ct || 'unknown'}; body: ${text.slice(0, 200)}`)
			}
		})
	}

	window.api = api
}

